#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<errno.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<unistd.h>
#include "DES.c"

#define MAXLINE 4096

int K_ss[64] = {0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0,
                1, 1, 1, 0, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1 };

char SSsendE[4096];
char SSsendG[4096];
char SSsendH[4096];

void intToString(int a[][64], int size, char* sendline) {
    int index = 0;
    for (int i = 0; i < size; ++i) {
        for (int j = 0; j < 64; ++j) {
            sendline[index++] = a[i][j] + 48;
        }
    }
    sendline[index] = '\0';
}


int main(int argc, char** argv){
    int  listenfd, connfd;    
    struct sockaddr_in  servaddr;
    char  buff[4096];
    int  n;
    if( (listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1 ){
        printf("create socket error: %s(errno: %d)\n",strerror(errno),errno);
        return 0;
   }

    memset(&servaddr, 0, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");
    servaddr.sin_port = htons(8082);

    if(bind(listenfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) == -1){
        printf("bind socket error: %s(errno: %d)\n",strerror(errno),errno);
        return 0;
    }

    if(listen(listenfd, 10) == -1){
        printf("listen socket error: %s(errno: %d)\n",strerror(errno),errno);
        return 0;
    }

    printf("======waiting for client's request======\n");
    while(1){
        //accept发生阻塞
        if((connfd = accept(listenfd, (struct sockaddr*)NULL, NULL)) == -1){
            printf("accept socket error: %s(errno: %d)",strerror(errno),errno);
            continue;
        }
        n = recv(connfd, SSsendE, MAXLINE, 0);
        SSsendE[n] = '\0';
        printf("消息E: %s\n", SSsendE);

        n = recv(connfd, SSsendG, MAXLINE, 0);
        SSsendG[n] = '\0';
        printf("消息G: %s\n", SSsendG);

       
        //从消息E中提取ST
        char ST[4096];
        for (int i = 8; i < strlen(SSsendE); ++i) {
            ST[i-8] = SSsendE[i];
        }

        ST[strlen(SSsendE)-8] = '\0';

        //对ST进行解密，得到k_client_ss
        int STInt[100][64];
        int plainST[100][64];
        for (int i = 0; i < strlen(ST); ++i) {
            int k = i / 64;
            int j = i % 64;
            STInt[k][j] = ST[i] - 48;
        } 

        int sizeST = strlen(ST) / 64;
        for (int i = 0; i < sizeST; ++i) {
            decrypt(STInt[i], K_ss, plainST[i]);
        }   

        int k_client_ss[64];
        for (int i = 16; i < 64; ++i) {
            k_client_ss[i-16] = plainST[0][i];
        }

        for (int i = 0; i < 16; ++i) {
            k_client_ss[i+48] = plainST[1][i];
        }


        //对消息G进行解密
        int cipherGInt[100][64];
        int plainG[100][64];
        for (int i = 0; i < strlen(SSsendG); ++i) {
            int k = i / 64;
            int j = i % 64;
            cipherGInt[k][j] = SSsendG[i] - 48;
        } 

        int sizeG = strlen(SSsendG) / 64;
        for (int i = 0; i < sizeG; ++i) {
            decrypt(cipherGInt[i], k_client_ss, plainG[i]);
        } 

        //从消息G中提取clientID
        char clientID[4];
        for (int i = 0; i < 3; ++i) {
            clientID[i] = plainG[0][i] + 48;
        }
        clientID[3] = '\0';

        //从消息G中提取TS
        char TS[6];
        for (int i = 0; i < 5; ++i) {
            TS[i] = plainG[0][i+3] + 48;
        }
        TS[5] = '\0';

        //TS加1
        int TSval = 0;
        for (int i = 0; i < 5; ++i) {
            int a = (int)TS[i] - 48;
            TSval = TSval + (a << (4-i));
        }

        char TS1[6] = { '\0' };
        int TSval1 = TSval + 1;
        for (int i = 4; i >= 0; --i) {
            int a = TSval1 % 2;
            TSval1 = TSval1 / 2;
            TS1[i] = a + 48;
        }
        TS1[5] = '\0';

        //消息H
        char textH[4096] = {'\0'};
        strncat(textH, clientID, 4);
        strncat(textH, TS1, 6);

        size = 1;
        for (int i = 0; i < strlen(textH); ++i) {
            inputTexts[0][i] = textH[i];
        }

        manageText();

        int cipherH[size][64];
        for (int i = 0; i < size; ++i) {
            encrypt(input[i], k_client_ss, cipherH[i]);
        }

        intToString(cipherH, size, SSsendH);

        //发送消息H
        printf("======发送消息H给client======\n");
        printf("消息H: %s\n", SSsendH);
        if(send(connfd, SSsendH, strlen(SSsendH), 0) < 0){
            printf("send msg error: %s(errno: %d)\n", strerror(errno), errno);
        }



        close(connfd);


    }

    close(listenfd);
    return 0;
}